//
//  GroupMessageDataBase.m
//  AAIM
//
//  Created by awh on 2019/12/23.
//  Copyright © 2019年 AAIM. All rights reserved.
//

#import "GroupMessageDataBase.h"
#import "BTMessageModel.h"
#import "TextMessageModel.h"
#import "ImageMessageModel.h"
#import "VoiceMessageModel.h"

@interface GroupMessageDataBase ()

//@property(nonatomic, strong) FMDatabase *db;   // 数据数据库
@property(nonatomic, copy) NSString *tableName;

@property(nonatomic, strong) FMDatabaseQueue *dbQueue;
@end
@implementation GroupMessageDataBase
static GroupMessageDataBase *single = nil;

+ (instancetype)shareGroupMessageDataBase {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        single = [[self alloc] init];
    });
    return single;
}

- (instancetype)init {
    if (self = [super init]) {
        [self initDataBase];
    }
    return self;
}

- (void)initDataBase {
    NSString *dbPath  =[CacheTool readUserDefaults:@"APPDATABASE_KEY"];
    self.dbQueue = [[FMDatabaseQueue alloc] initWithPath:dbPath];
}

- (void)creatChatTable {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *createTableSql = [NSString stringWithFormat:@"create table if not exists %@ ('ID' INTEGER PRIMARY KEY AUTOINCREMENT, 'messageDirection' INTEGER, 'messageType' INTEGER,'uid' INTEGER, 'username' TEXT, 'avatar' TEXT, 'type' TEXT, 'src' TEXT, 'content' TEXT, 'time' TEXT, 'specialType' INTEGER, 'groupId' INTEGER, 'authority' INTEGER, 'mine' INTEGER, 'timestamp' INTEGER, 'updateTimestamp' INTEGER,  'cid' INTEGER, 'receiveUid' INTEGER, 'unreadCount' INTEGER, 'path' TEXT, 'image' BLOB, 'duration' INTEGER, 'messageStatus' INTEGER, 'messageId' INTEGER, 'msgtype' INTEGER, 'msg_id' TEXT, 'clientuuid' TEXT, 'createtime' TEXT, 'msg' TEXT, 'gId' TEXT, 'head' TEXT, 'f_uuid' TEXT, 'nickname' TEXT, 'token' TEXT, 'udid' TEXT, 'rfuuid' TEXT, 'chatType' INTEGER,'type_id' INTEGER)", self.tableName];
        [db executeUpdate:createTableSql];
    }];
    
}

- (void)insertMessage:(BTMessageModel *)msg {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *tableNameHead = [NSString stringWithFormat:@"insert into '%@' ", self.tableName];
        long long insertTime = [ChatTool shareChatTool].currentTimestamp;
        long long messageId = msg.messageDirection == MessageDirectionSend ? 0 : [msg.msg_id integerValue];
        BOOL result = NO;
        if (msg.msgtype == MessageTypeText || msg.msgtype == MessageTypeRecall || msg.msgtype == MessageTypeTime || msg.msgtype == MessageTypeInviteAddGroup ||msg.msgtype == MessageTypeMangerDeleteMember ||msg.msgtype == MessageTypeGroupDissolution ||msg.msgtype == MessageTypeStartGroupChatting ||msg.msgtype == MessageTypeAddedBlacklist ||msg.msgtype == MessageTypeNotInGroup ||msg.msgtype == MessageTypeNotFriend ||msg.msgtype == MessageTypeSendFailure||msg.msgtype == MessageTypeSendBanned ) {
            NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, messageStatus, messageId,msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType,type_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)"];
            NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
            result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), @(msg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType),@(msg.type_id)];
        } else if (msg.msgtype == MessageTypeImage) {
            ImageMessageModel *imageMsg = (ImageMessageModel *)msg;
            NSData *imageData = UIImagePNGRepresentation(imageMsg.image);
            NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, path, image, messageStatus, messageId,msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType,type_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)"];
            NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
            result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), imageMsg.path, imageData, @(imageMsg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType),@(msg.type_id)];
        } else if (msg.msgtype == MessageTypeVoice) {
            VoiceMessageModel *voiceMsg = (VoiceMessageModel *)msg;
            NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, path, duration, messageStatus, messageId,msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType,type_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)"];
            NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
            result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), voiceMsg.path, @(voiceMsg.duration), @(voiceMsg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType),@(msg.type_id)];
        }else if (msg.msgtype == MessageTypeSystem)
        {
            if (msg.type_id == SystemMessageAuditJoinGroup || msg.type_id == SystemMessageDeleteGroupMember || msg.type_id == SystemMessageMemberExit || msg.type_id == SystemMessageDeleteGroup) {
                NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, messageStatus, messageId,msgtype, msg , msg_id ,clientuuid , createtime, gId , head ,f_uuid ,nickname,token,udid,rfuuid,chatType,type_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? , ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?)"];
                NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
                result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), @(msg.messageStatus), @(messageId),@(msg.msgtype),msg.msg,msg.msg_id,msg.clientuuid,msg.createtime,msg.gId,msg.head,msg.fuuid,msg.nickname,msg.token,msg.udid,msg.rfuuid,@(msg.chatType),@(msg.type_id)];
            }
        }
    }];
}

- (void)insertMessagArray:(NSArray<BTMessageModel *> *)messages {
    AAIMLog(@"开始批量插入");
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        [db beginTransaction];
        BOOL isRollBack = NO;
        @try {
            NSString *tableNameHead = [NSString stringWithFormat:@"insert into '%@' ", self.tableName];
            long long insertTime = [ChatTool shareChatTool].currentTimestamp;
            __block BOOL result = NO;
            [messages enumerateObjectsUsingBlock:^(BTMessageModel * _Nonnull msg, NSUInteger idx, BOOL * _Nonnull stop) {
                long long messageId = msg.messageDirection == MessageDirectionSend ? 0 : [msg.msg_id integerValue];
                NSString *content = [NSString stringWithFormat:@"(messageDirection, messageType, uid, username, avatar, type, src, content, time, specialType, groupId, authority, mine, timestamp, updateTimestamp, cid, receiveUid, unreadCount, messageStatus, messageId) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"];
                NSString *sql = [NSString stringWithFormat:@"%@%@", tableNameHead, content];
                result = [db executeUpdate:sql, @(msg.messageDirection), @(msg.messageType), @(msg.uid), msg.username, msg.avatar, msg.type, msg.src, msg.content, msg.time, @(msg.specialType), @(msg.groupId), @(msg.authority), @(msg.mine), @(msg.timestamp), @(insertTime), @(msg.cid), @(msg.receiveUid), @(msg.unreadCount), @(msg.messageStatus), @(messageId)];
            }];
        } @catch (NSException *exception) {
            isRollBack = YES;
            [db rollback];
        } @finally {
            if (!isRollBack) {
                [db commit];
                AAIMLog(@"批量插入群聊消息完成");
            }
        }
    }];
}

// 清除时间戳之前的聊天记录
- (void)deleteMessageBeforeTimestamp:(long long)timestamp {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ where updateTimestamp < %lld;", self.tableName, timestamp];
        [db executeUpdate:sql];
    }];
}

- (void)updateMessage:(BTMessageModel *)msg statusTo:(MessageStatus)status {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"update %@ set messageStatus = %ld where timestamp = %lld;", self.tableName, status, msg.timestamp];
        [db executeUpdate:sql];
    }];
}

- (void)deleteMessage:(BTMessageModel *)msg {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ where (gId = %ld and timestamp = %lld);", self.tableName, [msg.gId integerValue], msg.timestamp];
        [db executeUpdate:sql];
    }];
}

// 根据uid更新头像
- (void)updateAvatarWithUid:(NSInteger)uid avatar:(NSString *)avatar {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"update %@ set head = '%@' where uid = '%ld'", self.tableName, avatar, uid];
        [db executeUpdate:sql];
    }];
}

// 根据uid更新昵称
- (void)updateUsernameWithUid:(NSInteger)uid username:(NSString *)username {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"update %@ set username = '%@' where uid = '%ld'", self.tableName, username, (long)uid];
        [db executeUpdate:sql];
    }];
}

- (void)clearAllMessageWithGroupId:(NSInteger)groupId {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@ where gId = %ld", self.tableName, (long)groupId];
        [db executeUpdate:sql];
    }];
}

- (void)clearAllMessageWithAllGroups {
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"delete from %@", self.tableName];
        [db executeUpdate:sql];
    }];
}

// 根据groupId和聊天内容模糊搜索
- (NSArray<BTMessageModel *> *)queryMessagesWithGroupId:(NSInteger)groupId byContent:(NSString *)content {
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where (gId = %ld and content like '%%%@%%')", self.tableName, groupId, content];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    return messages;
}

//查询所有群
- (NSArray<BTMessageModel *> *)queryGroupMessagesWithKeyWord:(NSString *) keyWord {
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where  msg like '%%%@%%'", self.tableName, keyWord];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    return messages;
}


- (BTMessageModel *)recentlyMessageWithGroupId:(NSInteger)groupId {
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where gId = %ld order by timestamp desc limit 0,1", self.tableName, (long)groupId];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    if (messages.count) {
        return messages[0];
    } else {
        return nil;
    }
}

- (NSArray<BTMessageModel *> *)queryAllMessagesWithGroupId:(NSInteger)groupId {
    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where gId = %ld and updateTimestamp > %lld", self.tableName, (long)groupId, fromTime];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
    }];
    return messages;
}

// 分页加载，每页20条
- (NSArray *)queryMessagesWithGroupId:(NSInteger)groupId toTimestamp:(long long) toTimestamp {
//    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
//    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        if (toTimestamp == 0) { // 加载第一页
            NSString *sql = [NSString stringWithFormat:@"select * from %@ where gId = %ld order by timestamp desc, msgtype asc limit 0,20", self.tableName, (long)groupId];
            FMResultSet *result = [db executeQuery:sql];
            while ([result next]) {
                [messages addObject:[self messageWith:result]];
            }
        } else {
            NSString *sql = [NSString stringWithFormat:@"select * from %@ where gId = %ld and timestamp < %lld order by timestamp desc, msgtype asc limit 0,20", self.tableName, (long)groupId, toTimestamp];
            FMResultSet *result = [db executeQuery:sql];
            while ([result next]) {
                [messages addObject:[self messageWith:result]];
            }
        }
    }];
    return messages;
}

// 加载最新的count条数据
- (NSArray *)queryMessagesWithGroupId:(NSInteger)groupId count:(NSInteger)count {
//    long long fromTime = [ChatTool shareChatTool].currentTimestamp - 3 * 60 * 60 * 1000;
//    [self deleteMessageBeforeTimestamp:fromTime];
    NSMutableArray *messages = [NSMutableArray new];
    [self.dbQueue inDatabase:^(FMDatabase *db) {
        NSString *sql = [NSString stringWithFormat:@"select * from %@ where gId = %ld order by timestamp desc, msgtype asc limit 0,%ld", self.tableName, (long)groupId, (long)count];
        FMResultSet *result = [db executeQuery:sql];
        while ([result next]) {
            [messages addObject:[self messageWith:result]];
        }
        [messages reverse];
    }];
    return messages;
}

- (BTMessageModel *)messageWith:(FMResultSet *)result {
    BTMessageModel *msg = [BTMessageModel new];
    msg.messageType = [result intForColumn:@"messageType"];
    msg.messageDirection = [result intForColumn:@"messageDirection"];
    msg.uid = [result intForColumn:@"uid"];
    msg.username = [result stringForColumn:@"username"];
    msg.avatar = [result stringForColumn:@"avatar"];
    msg.type = [result stringForColumn:@"type"];
    msg.src = [result stringForColumn:@"src"];
    msg.content = [result stringForColumn:@"content"];
    msg.time = [result stringForColumn:@"time"];
    msg.specialType = [result intForColumn:@"specialType"];
    msg.groupId = [result intForColumn:@"groupId"];
    msg.authority = [result intForColumn:@"authority"];
    msg.mine = [result intForColumn:@"mine"];
    msg.timestamp = [result longLongIntForColumn:@"timestamp"];
    msg.cid = [result longLongIntForColumn:@"cid"];
    msg.receiveUid = [result intForColumn:@"receiveUid"];
    msg.unreadCount = [result intForColumn:@"unreadCount"];
    msg.messageStatus =  [result intForColumn:@"messageStatus"];
    msg.messageId = [result longLongIntForColumn:@"messageId"];
    
    msg.msgtype=[result intForColumn:@"msgtype"];
    msg.msg_id=[result stringForColumn:@"msg_id"];
    msg.clientuuid= [result stringForColumn:@"clientuuid"];
    msg.msg = [result stringForColumn:@"msg"];
    msg.gId = [result stringForColumn:@"gId"];
    msg.head=[result stringForColumn:@"head"];
    msg.f_uuid=[result stringForColumn:@"f_uuid"];
    msg.nickname=[result stringForColumn:@"nickname"];
    msg.token=[result stringForColumn:@"token"];
    msg.udid=[result stringForColumn:@"udid"];
    msg.createtime=[result stringForColumn:@"createtime"];
    msg.chatType = [result intForColumn:@"chatType"];
    msg.rfuuid=[result stringForColumn:@"rfuuid"];
    msg.type_id=[result intForColumn:@"type_id"];

    
    if (msg.msgtype == MessageTypeText || msg.msgtype == MessageTypeRecall || msg.msgtype == MessageTypeTime || msg.msgtype == MessageTypeInviteAddGroup ||msg.msgtype == MessageTypeMangerDeleteMember ||msg.msgtype == MessageTypeGroupDissolution ||msg.msgtype == MessageTypeStartGroupChatting ||msg.msgtype == MessageTypeAddedBlacklist ||msg.msgtype == MessageTypeNotInGroup ||msg.msgtype == MessageTypeNotFriend ||msg.msgtype == MessageTypeSendFailure  ||msg.msgtype == MessageTypeSendBanned ) {
        return msg;
    } else if (msg.msgtype == MessageTypeImage) {
        ImageMessageModel *imageMsg = [ImageMessageModel mj_objectWithKeyValues:msg.mj_keyValues];
        imageMsg.image = [UIImage imageWithData:[result dataForColumn:@"image"]];
        imageMsg.path = [result stringForColumn:@"path"];
        return imageMsg;
    } else if (msg.msgtype == MessageTypeVoice) {
        VoiceMessageModel *voiceMsg = [VoiceMessageModel mj_objectWithKeyValues:msg.mj_keyValues];
        voiceMsg.path = [result stringForColumn:@"path"];
        voiceMsg.duration = [result intForColumn:@"duration"];
        return voiceMsg;
    }else if (msg.msgtype== MessageTypeSystem)
    {
        if (msg.type_id == SystemMessageAuditJoinGroup || msg.type_id == SystemMessageDeleteGroupMember || msg.type_id == SystemMessageMemberExit || msg.type_id == SystemMessageDeleteGroup) {
            return msg;
        }
    }
    return nil;
}

#pragma mark - getter

- (NSString *)tableName {
    UserModel * model_user= [[LoginManager shareLoginManager] getLoginCustomer];
    return  [NSString stringWithFormat:@"t_groupMessageList_%@", model_user.fuuid];
}
@end
